﻿using Microsoft.LightSwitch;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;

namespace LightSwitchApplication.UserCode
{
    /// <summary>
    /// Everything to set up the Database, plus Methods which should be launched by the server 
    /// Every change in Init Mathods must de double checked (Static ID i. e.!)
    /// otherwise it could brake existing properties
    /// </summary>
    public class ServerJobs
    {
        private ApplicationData ApplicationData;

        public ServerJobs(ApplicationData appData)
        {
            ApplicationData = appData;
        }

        public void StartServerJob(tbServerJob job)
        {
            if (!job.IsReady)
                return;

            TimeSpan TimeOut = new TimeSpan(0, 30, 0);    // Lets assume 30 Minutes Timeout
            DateTime calcTimeOut = job.Started + TimeOut;
            if (job.Timeout == calcTimeOut && job.Timeout < DateTime.Now)
                return;
            
            job.Timeout = job.Started + TimeOut;

            // FirstInit is a little special...
            if (job.Name == "FirstInit")
            {
                FirstInit(job);
                return;
            }

            setStatus(job, 1); // Initialised

            switch (job.Name)
            {
                case "InitTbStatus":
                    InitTbStatus(job);
                    break;
                case "InitIntervals":
                    InitIntervals(job);
                    break;
                case "InitStaticProperties":
                    InitStaticProperties(job);
                    break;
                /*case "CreateTrainsession":
                    CreateTrainsession(job);
                    break;*/
                default:
                    break;
            }

            FinalizeJob(job);
        }

        private void FirstInit(tbServerJob job)
        {
            InitTbStatus(job);
            InitIntervals(job);
            InitStaticProperties(job);
            FinalizeJob(job);
        }

        #region InitTlInterval
        private void InitIntervals(tbServerJob job)
        {
            setStatus(job, 2); // Started
            // Weekly Interval
            tlInterval Weekly = createInterval(1, "Wöchentlich");
            if (Weekly != null)
            {
                createIntervalValue(1, 1, "Montag", Weekly);
                createIntervalValue(2, 2, "Dienstag", Weekly);
                createIntervalValue(3, 3, "Mittwoch", Weekly);
                createIntervalValue(4, 4, "Donnerstag", Weekly);
                createIntervalValue(5, 5, "Freitag", Weekly);
                createIntervalValue(6, 6, "Samstag", Weekly);
                createIntervalValue(7, 7, "Sonntag", Weekly);
            }

            // Monthly Interval
            tlInterval Monthly = createInterval(3, "Monatlich");
            if (Monthly != null)
            {
                for (int i = 1; i <= 31; i++)
                {
                    createIntervalValue(i, i, i.ToString() + ".", Monthly);
                }
            }
        }

        private tlInterval createInterval(int StaticId, string Name)
        {
            IEnumerable<tlInterval> query = (from s in ApplicationData.tlIntervalSet
                                             where s.StaticId == StaticId
                                             select s).Execute();

            if (query.Count() > 0)
                return query.FirstOrDefault();

            tlInterval result = ApplicationData.tlIntervalSet.AddNew();
            result.StaticId = StaticId;
            result.Name = Name;
            return result;
        }

        private tlIntervalValue createIntervalValue(int StaticId, int Value, string Name, tlInterval Interval)
        {
            IEnumerable<tlIntervalValue> query = (from s in ApplicationData.tlIntervalValueSet
                                                  where s.StaticId == StaticId
                                                    && s.tlInterval.StaticId == Interval.StaticId 
                                                  select s).Execute();

            if (query.Count() > 0)
                return query.FirstOrDefault();

            tlIntervalValue result = ApplicationData.tlIntervalValueSet.AddNew();
            result.StaticId = StaticId;
            result.Value = Value;
            result.Name = Name;
            result.tlInterval = Interval;
            return result;
        }
        #endregion InitTlInterval

        # region InitTbStatus
        private void InitTbStatus(tbServerJob job)
        {
            // Define status
            List<tlJobStatus> StatusList = new List<tlJobStatus>();
            
            StatusList.Add(createStatus(1, "Initialised"));
            StatusList.Add(createStatus(2, "Started"));
            StatusList.Add(createStatus(3, "Completed"));   
        }

        private tlJobStatus createStatus(int StaticId, string Name)
        {
            IEnumerable<tlJobStatus> query = (from s in ApplicationData.tlJobStatusSet
                                              where s.StaticId == StaticId
                                              select s).Execute();
            
            if (query.Count() > 0)
                return query.FirstOrDefault();

            tlJobStatus result = ApplicationData.tlJobStatusSet.AddNew();
            result.StaticId = StaticId;
            result.Name = Name;
            return result;
        }
        # endregion InitTbStatus

        #region InitStaticProperties
        private void InitStaticProperties(tbServerJob job)
        {
            setStatus(job, 2); // Started
            tlCustomProperty role = createCustomProperty(1, "Vereinsrolle", true);
            tlCustomProperty type = createCustomProperty(2, "Teilnehmer Typ", true);
            tlCustomProperty attandanceType = createCustomProperty(3, "Teilnahme Status", true);

            createCustomProperty(4, "eMail-Adresse", false);

            // Vereinsrolle
            createCustomPropertyChoices(1, "Mitglied", role);
            createCustomPropertyChoices(2, "Trainer", role);
            createCustomPropertyChoices(3, "Spartenleitung", role);

            // Teilnehmer Typ
            createCustomPropertyChoices(4, "Teilnehmer", type);
            createCustomPropertyChoices(5, "Trainer", type);

            // Teilnahme Status
            createCustomPropertyChoices(6, "Anwesend", attandanceType);
            createCustomPropertyChoices(7, "Verspätet", attandanceType);
            createCustomPropertyChoices(8, "Entschuldigt", attandanceType);
            createCustomPropertyChoices(9, "Unentschuldigt", attandanceType);
            createCustomPropertyChoices(10, "- Kein Datensatz", attandanceType);
        }

        private tlCustomProperty createCustomProperty(int StaticId, string Name, bool IsChooseable)
        {
            IEnumerable<tlCustomProperty> query = (from s in ApplicationData.tlCustomPropertySet
                                                   where s.StaticId == StaticId
                                                   select s).Execute();

            if (query.Count() > 0)
                return query.FirstOrDefault();

            tlCustomProperty result = ApplicationData.tlCustomPropertySet.AddNew();
            result.StaticId = StaticId;
            result.PropertyName = Name;
            result.IsChooseable = IsChooseable;
            result.IsBoundStatically = true;

            return result;
             
        }

        private tlCustomPropertyChoices createCustomPropertyChoices(int StaticId, string Name, tlCustomProperty Property)
        {
            IEnumerable<tlCustomPropertyChoices> query = (from s in ApplicationData.tlCustomPropertyChoicesSet
                                                          where s.StaticId == StaticId
                                                             && s.tlCustomProperty.StaticId == Property.StaticId
                                                          select s).Execute();
            
            if (query.Count() > 0)
                return query.FirstOrDefault();

            tlCustomPropertyChoices result = ApplicationData.tlCustomPropertyChoicesSet.AddNew();
            result.StaticId = StaticId;
            result.Name = Name;
            result.IsBoundStatically = true;
            result.tlCustomProperty = Property;
            return result;
        }

        #endregion InitStaticProperties

        /*
        #region CreateTrainsession
        private void CreateTrainsession(tbServerJob job)
        {
            DateTime Start;
            DateTime End;
            bool IntervalOverride;
            int TraingroupId;

            if (!CreateTrainsessionParse(job, out Start, out End, out IntervalOverride, out TraingroupId))
                return;

            tbTrainsession session = ApplicationData.tbTrainsessionSet.AddNew();
            
            // Start
            session.GroupStart = Start;
            
            // End
            session.GroupEnd = End;
            
            // Internal Override
            session.IntervalOverride = IntervalOverride;

            // Stakeholder Relation
            IEnumerable<tbStakeholder> stakeholder = (from s in ApplicationData.tbStakeholderSet
                                                      where s.trTraingroupStakeholder.Any(x => x.tlTraingroup.Id == TraingroupId)
                                                      select s).Execute();

            tlCustomProperty cp = (from s in ApplicationData.tlCustomPropertySet
                                   where s.StaticId == 3            // Teilnahme Status
                                   select s).Execute().FirstOrDefault();

            tlCustomPropertyChoices cpv = (from s in ApplicationData.tlCustomPropertyChoicesSet
                                           where s.StaticId == 6    // Anwesend
                                              && s.tlCustomProperty.StaticId == 3    // Teilnahme Status
                                           select s).Execute().FirstOrDefault();

            foreach (tbStakeholder sh in stakeholder)
            {
                trStakeholderTrainsession newRelation = ApplicationData.trStakeholderTrainsessionSet.AddNew();
                newRelation.tbTrainsession = session;
                newRelation.tbStakeholder = sh;
                newRelation.tlCustomProperty = cp;
                newRelation.tlCustomPropertyChoices = cpv;
                newRelation.Checked = false;
            }

            // Traingroup Relation
            session.tlTraingroup = (from s in ApplicationData.tlTraingroupSet
                                    where s.Id == TraingroupId
                                    select s).Execute().FirstOrDefault();

            //this.ApplicationData.SaveChanges();
            this.FinalizeJob(job);
        }

        private bool CreateTrainsessionParse(tbServerJob job, out DateTime pStart, out DateTime pEnd, out bool pIntervalOverride,
            out int pTraingroupId)
        {
            setStatus(job, 2);  // Started
            bool error = false;
            CultureInfo culture = new CultureInfo("de-DE");
            DateTimeStyles style = DateTimeStyles.None;

            if (!DateTime.TryParse(GetParameter("Start", job), culture, style, out pStart))
            {
                error = true;
                job.ErrorText += "Start parse error. ";

            }

            if (!DateTime.TryParse(GetParameter("End", job), culture, style, out pEnd))
            {
                error = true;
                job.ErrorText += "End parse error. ";

            }
            
            if (!bool.TryParse(GetParameter("IntervalOverride", job), out pIntervalOverride))
            {
                error = true;
                job.ErrorText += "IntervalOverride parse error. ";

            }

            if (!int.TryParse(GetParameter("TraingroupId", job), out pTraingroupId))
            {
                error = true;
                job.ErrorText += "TraingroupId parse error. ";

            }

            if (error)
                return false;
            return true;
        }
        #endregion CreateTrainsession
        */

        private void FinalizeJob(tbServerJob job)
        {
            job.Finished = DateTime.Now;
            setStatus(job, 3); // Completed
        }

        private void setStatus(tbServerJob job, int StatusStaticId)
        {
            try
            {
                tlJobStatus Status = (from s in ApplicationData.tlJobStatusSet
                                      where s.StaticId == StatusStaticId 
                                      select s).First();
                job.tlJobStatus = Status;
            }
            catch
            {
                job.ErrorText += "Server status not found! ";
                //job.tlJobStatus = null;
            }
        }

        private string GetParameter(string ParameterName, tbServerJob job)
        {
            IEnumerable<tbServerJobParameter> query = (from s in ApplicationData.tbServerJobParameterSet
                                                       where s.tbServerJob.Id == job.Id
                                                          && s.Name == ParameterName
                                                       select s).Execute();

            if (query.FirstOrDefault() == null)
                return null;

            tbServerJobParameter parameter = query.FirstOrDefault();
            return parameter.Value;
        }
    }
}